#include	"board.h"
#include  	<rtthread.h>   //这个和rt-thread的内核相关

//#define STM32F103C8T6

#ifdef  STM32F103C8T6
/*******这里都是针对中容量产品(64KB)*******/
#define FLASH_PAGE_SIZE    ((uint16_t)0x400)	//1024
#define START_PAGE_ADDRESS	0x0800FC00      //参数的起始地址(他选的是最后一页)               start:0x0800 FC00       end:0x0801 0000           1KB=0x0400
#else
/*******这里都是针对大容量产品(512KB)*******/
#define FLASH_PAGE_SIZE    ((uint16_t)0x800)	//2048
#define START_PAGE_ADDRESS	0x0807F800      //参数的起始地址(他选的是最后一页)                start:0x0807 F800       end:0x0807 FFFF          2KB=0x0800
#endif

#define KEY_NUM   4
static uint8_t key_state[KEY_NUM]={1,1,1,1};       //定义按键当前状态数组变量(这个是未按下时)
SYSTEM_STATE  system_state=SYSTEM_NORMAL;        //当前系统状态枚举变量
static d_union_mail dryballcor;                  //这个是干球温度的备份值  主要用于判断当前校正值是否需要被存进FLASH中
static d_union_mail humitballcor;                //这个是湿球温度的备份值
static uint8_t index=1;                          //光标索引

/**
  * @brief	从单片机FLASH中读取相关参数
  *	@param	void
  * @retval void
  */
void ReadPar(void) 
{   //标准库中没有相应的读取函数
    d_union_mail buff[2];   //这个类型在main.h中有定义

    buff[0].dat_li=*((volatile uint32_t *)(START_PAGE_ADDRESS));
    buff[1].dat_li=*((volatile uint32_t *)(START_PAGE_ADDRESS+4));  //float占4字节故得加4
    if(buff[0].dat_li==0xFFFFFFFF)
    {
      buff[0].dat_f=0.0;    //初次使用时初始化为0 (对应干球温度)
    }
    if(buff[1].dat_li==0xFFFFFFFF)
    {
      buff[1].dat_f=0.0;    //初次使用时初始化为0(对应湿球温度)
    }
    dryballcor.dat_f=dryballcorrection.dat_f=buff[0].dat_f;   //干球温度
    humitballcor.dat_f=humitballcorrection.dat_f=buff[1].dat_f;   //湿球温度
}

/**
  * @brief	将相关数据存进单片机FLASH
  *	@param	void
  * @retval void
  */
static void SavePar(void) 
{
    /*先判断当前校正值是否发生了变化,发生了变化才进行存储*/
    if((dryballcor.dat_li!=dryballcorrection.dat_li) || (humitballcor.dat_li !=humitballcorrection.dat_li))
    { /*不一样，先备份*/
      dryballcor.dat_f=dryballcorrection.dat_f;   //干球温度
      humitballcor.dat_f=humitballcorrection.dat_f;   //湿球温度
      /*下面就开始正式的进行数据存储*/
      /* 解锁 */
      FLASH_Unlock();
      FLASH_ErasePage(START_PAGE_ADDRESS);    //对于中容量的单片机FLASH大小为64KB 大容量的单片机FLASH容量为512KB
      FLASH_ProgramWord(START_PAGE_ADDRESS,dryballcor.dat_li);
      FLASH_ProgramWord(START_PAGE_ADDRESS+4,humitballcor.dat_li);
      FLASH_Lock();
      /*这里只是进行测试*/
      led_data_mail.index =1;
      rt_mb_send(led_mail, (rt_int32_t)(&led_data_mail)); //发送邮箱
    }
}

/**
  * @brief	设置按键(用于设置及退出)
  *	@param	void
  * @retval void
  */
static void SetKey(void)
{
  if(system_state==SYSTEM_NORMAL) //系统处于正常状态时才可进入设置状态
  { //进入设置界面
    TIM_Cmd(BASIC_TIM,DISABLE);   //关定时器  主要是让显示屏不再刷新显示
    system_state=SYSTEM_SET; 
    lcd_data_mailNST.dat_u[0].dat_i[2]=0;
    lcd_data_mailNST.dat_u[0].dat_i[1]=0x01;
    lcd_data_mailNST.index = 3;
    rt_mb_send(lcd_mail, (rt_int32_t)(&lcd_data_mailNST)); //发送邮箱
  }
  else if(system_state==SYSTEM_SET)
  { //退出设置界面
    index=1;
    lcd_data_mailNST.dat_u[0].dat_i[2]=0;
    lcd_data_mailNST.dat_u[0].dat_i[1]=0;  //不反色
    lcd_data_mailNST.index = 3;
    rt_mb_send(lcd_mail, (rt_int32_t)(&lcd_data_mailNST)); //发送邮箱
    system_state=SYSTEM_NORMAL;      
    SavePar();    //退出设置界面之前即进行参数存储
    TIM_Cmd(BASIC_TIM,ENABLE);   //开定时器  主要是让显示屏刷新显示
  }
}

/**
  * @brief	位移按键(选则要设置的选项)
  *	@param	void
  * @retval void
  */
static void ShiftKey(void)
{
  uint8_t flag1=0;    //负数指示
  uint8_t flag2=0;    //负数指示

    if(system_state==SYSTEM_SET)
    {
      ++index;
      if(index>6)
      {
        index=1;
      }
      // if((dat.dat_u[1].dat_f+dryballcorrection.dat_f)<0)
      // {
      //   flag1=1;
      // }
      // if((dat.dat_u[2].dat_f+humitballcorrection.dat_f)<0)
      // {
      //   flag2=1;        
      // }
      switch (index)
      {
        case 1:lcd_data_mailNST.dat_u[0].dat_i[1]=0x01;lcd_data_mailNST.dat_u[0].dat_i[2]=0;break;
        case 2:lcd_data_mailNST.dat_u[0].dat_i[1]=0x02;lcd_data_mailNST.dat_u[0].dat_i[2]=0;break;
        case 3:lcd_data_mailNST.dat_u[0].dat_i[1]=0x08;lcd_data_mailNST.dat_u[0].dat_i[2]=0;break;
        case 4:lcd_data_mailNST.dat_u[0].dat_i[1]=0;lcd_data_mailNST.dat_u[0].dat_i[2]=0x01;break;
        case 5:lcd_data_mailNST.dat_u[0].dat_i[1]=0;lcd_data_mailNST.dat_u[0].dat_i[2]=0x02;break;
        case 6:lcd_data_mailNST.dat_u[0].dat_i[1]=0;lcd_data_mailNST.dat_u[0].dat_i[2]=0x08;break;     
        default:break;
      }
      lcd_data_mailNST.index = 3;
      rt_mb_send(lcd_mail, (rt_int32_t)(&lcd_data_mailNST)); //发送邮箱
    }
}

/**
  * @brief	加按键
  *	@param	void
  * @retval void
  */
static void IncKey(void)
{
    if(system_state==SYSTEM_SET)
    {
      switch (index)
      {
        case 1:dryballcorrection.dat_f+=10;break;
        case 2:dryballcorrection.dat_f+=1;break;
        case 3:dryballcorrection.dat_f+=0.1;break;
        case 4:humitballcorrection.dat_f+=10;break;
        case 5:humitballcorrection.dat_f+=1;break;
        case 6:humitballcorrection.dat_f+=0.1;break;      
        default:break;
      }
      if(dryballcorrection.dat_f>20)
      {
        dryballcorrection.dat_f=20;
      }else if(dryballcorrection.dat_f<-20)
      {
        dryballcorrection.dat_f=-20;        
      }

      if(humitballcorrection.dat_f>20)
      {
        humitballcorrection.dat_f=20;
      }else if(humitballcorrection.dat_f<-20)
      {
        humitballcorrection.dat_f=-20;        
      }
      lcd_data_mailNST.index = 3;
      rt_mb_send(lcd_mail, (rt_int32_t)(&lcd_data_mailNST)); //发送邮箱
    }
}

/**
  * @brief	减按键
  *	@param	void
  * @retval void
  */
static void DecKey(void)
{
    if(system_state==SYSTEM_SET)
    {
      switch (index)
      {
        case 1:dryballcorrection.dat_f-=10;break;
        case 2:dryballcorrection.dat_f-=1;break;
        case 3:dryballcorrection.dat_f-=0.1;break;
        case 4:humitballcorrection.dat_f-=10;break;
        case 5:humitballcorrection.dat_f-=1;break;
        case 6:humitballcorrection.dat_f-=0.1;break;      
        default:break;
      }
      lcd_data_mailNST.index = 3;
      rt_mb_send(lcd_mail, (rt_int32_t)(&lcd_data_mailNST)); //发送邮箱
    }
}


/**
  * @brief	按键动作函数
  *	@param	keycode :键码
  * @retval void
  */
static void KeyAction(uint8_t keycode)
{
    switch (keycode)
    {
      case 1:SetKey();break; 
      case 2:IncKey();break;   
      case 3:DecKey();break;
      case 4:ShiftKey();break;
      default:break;
    }
}


/**
  * @brief	按键驱动函数(由按键前后的状态来判断按键是否按下或弹起)
  *	@param	void
  * @retval void
  */
void KeyDriver(void)
{
	static	uint8_t key_state_buff[KEY_NUM]={0,0,0,0};

	uint8_t i;
	
	for(i=0;i<KEY_NUM;++i)
	{
		if(key_state_buff[i]!=key_state[i])   //按键被按下或弹起(只执行变化时的值)
		{
			//备份按键的状态
			key_state_buff[i]=key_state[i];
			if(key_state[i]==0)  //按键弹起
			{
				//调用KeyAction函数
				KeyAction(i+1);
			}
		}
	}
}

/**
  * @brief	按键IO口配置函数
  *	@param	void
  * @retval void
  */
void Key_GPIO_Config(void)
{
    GPIO_InitTypeDef	GPIO_InitStructure;

    /****开启与按键端口相关的时钟********/
    RCC_APB2PeriphClockCmd(KEY1_GPIO_CLK|KEY2_GPIO_CLK|KEY3_GPIO_CLK|KEY4_GPIO_CLK,ENABLE);

    //按键1  SET按键
    GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING ;
    GPIO_InitStructure.GPIO_Pin=KEY1_GPIO_PIN;
    //这里是输入模式，故不需要配置速度
    GPIO_Init(KEY1_GPIO_PORT,&GPIO_InitStructure);

    //按键2  INC按键
    GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING ;
    GPIO_InitStructure.GPIO_Pin=KEY2_GPIO_PIN;
    //这里是输入模式，故不需要配置速度
    GPIO_Init(KEY2_GPIO_PORT,&GPIO_InitStructure);

    //按键3   DEC按键
    GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING ;
    GPIO_InitStructure.GPIO_Pin=KEY3_GPIO_PIN;
    //这里是输入模式，故不需要配置速度
    GPIO_Init(KEY3_GPIO_PORT,&GPIO_InitStructure);

    //按键4   SHIFT按键
    GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING ;
    GPIO_InitStructure.GPIO_Pin=KEY4_GPIO_PIN;
    //这里是输入模式，故不需要配置速度
    GPIO_Init(KEY4_GPIO_PORT,&GPIO_InitStructure);
}

/**
  * @brief	按键扫描函数,通过软件滤波来更新当前的按键状态
  *	@param	void
  * @retval void
  */
void Key_Scan(void)
{
	static uint8_t key_buffer[KEY_NUM]={0x00,0x00,0x00,0x00};   //软件滤波用数组(这里的按键，未按下时为低电平)
	uint8_t i=0;
	
	key_buffer[0]=(key_buffer[0]<<1)|((uint8_t)KEY(3));           //采样SET按键
	key_buffer[1]=(key_buffer[1]<<1)|((uint8_t)KEY(4));           //采样INC按键
	key_buffer[2]=(key_buffer[2]<<1)|((uint8_t)KEY(5));           //采样DEC按键
	key_buffer[3]=(key_buffer[3]<<1)|((uint8_t)KEY(6));           //采样SHIFT按键	
	for(i=0;i<KEY_NUM;++i)
	{
		if((key_buffer[i]&0x0F)==0x00)
		{
			key_state[i]=0;   //未按下
		}
		else if((key_buffer[i]&0x0F)==0x0F)
		{
			key_state[i]=1;   //按下了
		}
	}
}



